class MVue {
  constructor(options){
    this.$options = options

    // 数据响应化
    this.$data = options.data;
    this.observe(this.$data)

    // new Watcher();
    // this.$data.test
    // new Watcher();
    // this.$data.foo.bar
    new Compile(options.el, this)

    if(options.created){
      options.created.call(this)
    }
  }


  // 利用数据劫持
  observe(data){
    if(!data || typeof data !== 'object'){
      return;
    }
    // 遍历对象
    Object.keys(data).forEach(key => {
      this.defineReactive(data, key, data[key])

      // 代理data属性到vue上
      this.proxyData(key)
    })
  }

  defineReactive(data, key, val){
    this.observe(val) // 递归解决嵌套

    const dep = new Dep()

    Object.defineProperty(data, key, {
      get(){
        Dep.target && dep.addDep(Dep.target)
        return val
      },
      set(newVal){
        if(newVal === val){
          return;
        }
        val = newVal;
        // console.log(`${key}属性更新了：${val}`)
        dep.notify()
      }
    })
  }

  proxyData(key){
    Object.defineProperty(this, key, {
      get(){
        return this.$data[key]
      },
      set(newVal){
        this.$data[key] = newVal
      }
    })
  }
}

// Dep 用来管理Watcher 依赖 每一个依赖针对单个的属性
class Dep {
  constructor(){
    // 这里存放若干依赖 一个watcher对应一个属性
    this.deps = []
  }

  addDep(dep){
    this.deps.push(dep)
  }

  notify(){
    this.deps.forEach(dep => dep.update())
  }
}

class Watcher {
  constructor(vm, key, cb){
    this.vm = vm
    this.key = key
    this.cb = cb
    // 将当前watcher实例指定到静态Dep属性的实例target
    Dep.target = this
    this.vm[this.key] // 触发getter添加依赖
    Dep.target = null
  }

  update(){
    console.log('属性更新了')
    this.cb.call(this.vm, this.vm[this.key])
  }


}